
/*
 * 版权声明 (c) 2025 XXX科技有限公司
 *
 * 本软件及其相关文档文件受版权保护。未经版权所有者明确书面许可，任何单位或个人不得
 * 以任何形式复制、传播、修改、出售、出租、反向工程、反编译或利用本软件的任何部分。
 *
 * 对于任何违反本声明的行为，版权所有者保留追究法律责任的权利。
 */

/**********************************************************
 * 说明：
 * 	Socket网络相关的库文件、宏、结构体/类和常用函数等
 *********************************************************/

#ifndef __SOCKET_H__
#define __SOCKET_H__

#include "utils/header_sock.h"
#include "log.h"
#include "utils/tools.h"
#include <string>
#include <iostream>
#include <functional>
#include <fcntl.h>
#include <stdint.h>
#include <cstring>


using namespace std;

extern long long timestamp_mills();

/**
 * @brief 处理select多路复用选择器接收到的消息
 * @param fd			SocketFD
 * @param data			接收到的数据(未处理"\0")
 * @param len			数据长度
 * @param sender_ip		客户端IP(无需大小端转换)
 * @param sender_port	客户端Port(无需大小端转换)
 * @example
 *	使用实例：
 *	listen_handler foo() {
 *		return [this](int fd, const char *data, ssize_t len, const char *sender_ip, const ushort sender_port) {
 *			log_info("[MultiCast] recerived from{ %s:%d }  data: { %.*s } ...", sender_ip, sender_port, len, data);
 *		};
 *	 }
 *
 * 	异常示例： 未处理\0, 可能会引发异常
 * 	printf("data_1: %s\n", data);
 *
 * 	正确示例： 处理\0, 长度限定
 *  printf("data_2: %.*s\n", (int) len, data);
 *
 * 	正确示例： 处理\0, 手动添加\0
 *  char buffer[len + 1];
 *  memcpy(buffer, data, len + 1);
 *  buffer[len + 1] = '\0';
 *  printf("data_3: %s\n", buffer);
 */
using listen_handler = function<void(int fd, const char *data, ssize_t len, const char *sender_ip, const ushort sender_port)>;

/// @brief Socket监听器
struct Listener {
	const char    *name;       //  监听器名称(识别业务)
	int            sockfd = 0; // 套接字
	uint16_t       port   = 0; // 监听端口
	listen_handler handler;    // 处理程序
	long long      created;    // 创建时间

	Listener(int fd = -1, uint16_t _port = 0, const char *name = "DEFAULT") //
	    : name(name), sockfd(fd), port(_port), handler(nullptr) {
		created = timestamp_mills();
	}
	~Listener() {
		if (sockfd != -1) close(sockfd);
	}
};

struct SockPortPair {
	uint16_t port;
	int      sockFd;
	void (*receiver)(int sockFd);
};

/// @brief 		创建Sock地址
/// @param addr Sock地址
/// @param port Sock端口
/// @return
struct sockaddr_in create_addr(const uint16_t &port = 0, const char *addr = "0.0.0.0");

/// @brief 		创建UDP套接字
/// @param port 如果为0，则不绑定端口
/// @return 	Socket套接字
int create_udp_socket(const uint16_t port = 0);

using fdport = pair<int, ushort>;

/// @brief 		动态创建UDP套接字
/// @return 	pair<SocketFd,Port>
fdport create_udp_socket_dynamic();

#endif //__SOCKET_H__
